﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;

namespace ImageAnalyze
{
    public class ImageAnalyzer
    {
        private const int SPAN = 47;
        public void Read(Image image)
        {
            var bitmap = new Bitmap(image);

            //int degree = 300;
            //bitmap = MethodBaseOnMemory(bitmap, degree);

            //bitmap.Save($"degree{degree}.jpg");
            var verticals = GetVerticals(bitmap);
            var horizontals = GetHorizontals(bitmap);
            TestVandH(bitmap, verticals, horizontals);

            var vse = verticals
                .SelectMany(x => x.Pixels.Select(p => p.Y))
                .ToLookup(x => x)
                .OrderByDescending(x => x.Count())
                .Take(8)
                .Select(x => x.Key)
                .ToArray();

            var hse = horizontals
                .SelectMany(x => x.Pixels.Select(p => p.X))
                .ToLookup(x => x)
                .OrderByDescending(x => x.Count())
                .Take(8)
                .Select(x => x.Key)
                .ToArray();

            var startx = hse.Min();
            var endx = hse.Max();
            var starty = vse.Min();
            var endy = vse.Max();

            TestRect(bitmap, startx, endx, starty, endy);
        }

        private List<LineSpans> GetVerticals(Bitmap image)
        {
            var horizontals = new List<LineSpans>();

            for (int i = 0; i < image.Width; i += SPAN)
            {
                var lastColor = Color.Transparent;
                var spans = new LineSpans(true, i);
                for (int j = 0; j < image.Height; j++)
                {
                    var clr = image.GetPixel(i, j);
                    if (!clr.Like(lastColor))
                    {
                        if (j > 3)
                        {
                            spans.Pixels.Add(new Pixel { Color = clr, X = i, Y = j });
                        }

                        lastColor = clr;
                    }
                }

                if (spans.Pixels.Count > 1)
                {
                    horizontals.Add(spans);
                }
            }

            return horizontals;
        }

        private List<LineSpans> GetHorizontals(Bitmap image)
        {
            var verticals = new List<LineSpans>();

            for (int i = 0; i < image.Height; i += SPAN)
            {
                var lastColor = Color.Transparent;
                var spans = new LineSpans(false, i);
                for (int j = 0; j < image.Width; j++)
                {
                    var clr = image.GetPixel(j, i);
                    if (!clr.Like(lastColor))
                    {
                        if (j > 3)
                        {
                            spans.Pixels.Add(new Pixel { Color = clr, X = j, Y = i });
                        }
                        lastColor = clr;
                    }
                }

                if (spans.Pixels.Count > 1)
                {
                    verticals.Add(spans);
                }
            }

            return verticals;
        }

        private void TestVandH(Bitmap image, List<LineSpans> vers, List<LineSpans> hors)
        {
            var img = new Bitmap(image, image.Width, image.Height);
            var gp = Graphics.FromImage(img);
            foreach (var ver in vers)
            {
                foreach (var pixel in ver.Pixels)
                {
                    gp.DrawEllipse(Pens.White, pixel.X - 2, pixel.Y - 2, 4, 4);
                }
            }
            foreach (var hor in hors)
            {
                foreach (var pixel in hor.Pixels)
                {
                    gp.DrawEllipse(Pens.Aqua, pixel.X - 2, pixel.Y - 2, 4, 4);
                }
            }
            img.Save($"tmpvh{DateTime.Now:HHmmssffff}.jpg");
        }
        private void TestRect(Bitmap image, int sx, int ex, int sy, int ey)
        {
            var img = new Bitmap(image, image.Width, image.Height);
            var gp = Graphics.FromImage(img);

            gp.DrawRectangle(new Pen(Color.Blue, 2), sx, sy, ex - sx, ey - sy);

            img.Save($"tmprect{DateTime.Now:HHmmssffff}.jpg");
        }

        public Bitmap MethodBaseOnMemory(Bitmap bitmap, int degree)
        {
            if (bitmap == null)
            {
                return null;
            }
            var deg = (100.0 + degree) / 100.0;

            var width = bitmap.Width;
            var height = bitmap.Height;

            var length = height * 3 * width;
            var rgb = new byte[length];

            var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            var scan0 = data.Scan0;
            System.Runtime.InteropServices.Marshal.Copy(scan0, rgb, 0, length);

            double gray = 0;
            for (int i = 0; i < rgb.Length; i += 3)
            {
                for (int j = 0; j < 3; j++)
                {
                    gray = (((rgb[i + j] / 255.0 - 0.5) * deg + 0.5)) * 255.0;
                    if (gray > 255)
                        gray = 255;

                    if (gray < 0)
                        gray = 0;
                    rgb[i + j] = (byte)gray;
                }
            }

            System.Runtime.InteropServices.Marshal.Copy(rgb, 0, scan0, length);// 此处Copy是之前Copy的逆操作
            bitmap.UnlockBits(data);
            return bitmap;
        }
    }
}
